Update sendCANFrame()

Since version 1.0.0.70, VSCPworks reads registers using CLASS2_LEVEL1_PROTOCOL, EXTENDED_PAGE_READ. In reply to this request, the VSCP node sends a few tens of register values to the bus. These frames are sent through the sendCANFrame() and subsequently vscp18fsendMsg() or ECANSendMessage() functions. If the microcontroller can’t clear the CAN send buffer fast enough, the current implementation of the code hangs. Time to update it.

Luckily the fix is simple. We’ll add use a new variable, sendTimer, to detect a 1 second timeout, and if a frame hasn’t been sent when this timeout occurs, we’ll break out of the deadlock.

First we’ll need to declare the following global variable:

unsigned short sendTimer = 0;                   // timer for sendCANFrame() function

Then we’ll need to make sure it gets incremented every second, so we’ll add the following into doApplicationOneSecondWork():

void doApplicationOneSecondWork( void )
{
	unsigned char i;
	unsigned char controlbits;

	sendTimer++;        // timer for sendCANFrame() function
...

Then we’ll need to update the sendCANFrame()-function:

int8_t sendCANFrame(uint32_t id, uint8_t dlc, uint8_t *pdata)       // Ake's Paris implementation
{
	uint8_t rv = FALSE;
	unsigned short i = 0;

	sendTimer = 0;
	while ( sendTimer < 1 ) {
		if ( ECANSendMessage( id, pdata, dlc, ECAN_TX_XTD_FRAME ) ) {		//when using ECAN
//        if ( vscp18f_sendMsg( id, pdata , dlc, CAN_TX_XTD_FRAME ) ) {		//when using the older CAN implementation
			rv = TRUE;
			break;
		}
	}

	vscp_omsg.flags = 0;

	return rv;
}

Et voila, sendCANFrame() now has a means to escape a deadlock when the CAN send buffer isn’t cleared fast enough.

Resources

Comments